import threading
import time

import kdl
from loguru import logger


class ProxyPool:
    def __init__(self, username, password, areas=('北京', '上海', '广东')):
        self.auth = kdl.Auth("oq2ahc8pw3vftx8bmcvl", "00jx1mm7gynm3t9j2hehtbhy8n70c304")
        self.client = kdl.Client(self.auth)
        self.username = username
        self.password = password
        self.areas = areas
        self.current_ip = []
        self.expiry_time = 0
        self.lock = threading.Lock()
        self._stop_event = threading.Event()

        # 初始化获取第一个IP
        self._update_proxy()
        # 启动后台检查线程
        self.check_thread = threading.Thread(target=self._check_loop, daemon=True)
        self.check_thread.start()

    def _update_proxy(self):
        """获取新代理并更新有效期"""
        try:
            new_ips = self.client.get_dps(
                num=1,
                sign_type='hmacsha1',
                format='json',
                pt=1,
                area=','.join(self.areas)
            )
            if new_ips and len(new_ips) > 0:
                new_ip = new_ips[0]
                expiry_info = self.client.get_dps_valid_time(
                    new_ip,
                    sign_type='hmacsha1'
                )
                self.current_ip.append(new_ip)
                self.expiry_time = int(expiry_info.get(new_ip, 0))
                logger.info(f"🟢更新代理: {new_ip} (剩余时间： {self.expiry_time}s)")
        except Exception as e:
            logger.info(f"🔴 Error updating proxy: {e}")

    def _check_loop(self):
        """后台检查循环"""
        while not self._stop_event.is_set():
            time.sleep(self.expiry_time / 3)
            try:
                with self.lock:
                    if self.expiry_time > 0:
                        # 获取实际剩余时间
                        expiry_info = self.client.get_dps_valid_time(
                            self.current_ip[-1],
                            sign_type='hmacsha1'
                        )
                        remaining = int(expiry_info.get(self.current_ip[-1], 0))
                        if remaining <= 76:
                            logger.info(f"代理 {self.current_ip[-1]} 剩余时间 ({remaining}s), 去更新中...")
                            self._update_proxy()
                        else:
                            self.expiry_time = remaining
                logger.info(f"🧰 代理 {self.current_ip[-1]} 剩余时间 ({self.expiry_time}s)")
            except Exception as e:
                if self.expiry_time <= 100:
                    self._update_proxy()
                    logger.info(f"🔴检查代理失败: {e}, 时间不足100s，去更新中...")
                else:
                    self.expiry_time -= self.expiry_time / 3
                    logger.info(f"🔴检查代理失败: {e}, 还剩下{self.expiry_time}s")

    def get_proxies(self):
        """获取当前有效代理配置"""
        with self.lock:
            if not self.current_ip:
                raise ValueError("🔴 没有可用代理")

            return {
                "http": f"http://{self.username}:{self.password}@{self.current_ip[-1]}/",
                "https": f"http://{self.username}:{self.password}@{self.current_ip[-1]}/"
            }

    def stop(self):
        """停止后台检查"""
        self._stop_event.set()
        self.check_thread.join()

    def get_fresh_proxy(self):
        """获取一个有效代理，如果当前代理过期则重新获取"""
        with self.lock:
            if self.current_ip:
                expiry_info = self.client.get_dps_valid_time(
                    self.current_ip[-1],
                    sign_type='hmacsha1'
                )
                remaining = int(expiry_info.get(self.current_ip[-1], 0))
                if remaining > 0:
                    return {
                        "http": f"http://{self.username}:{self.password}@{self.current_ip[-1]}/",
                        "https": f"http://{self.username}:{self.password}@{self.current_ip[-1]}/"
                    }
            logger.info("🔄 代理已过期，正在获取新代理...")
            self._update_proxy()
            time.sleep(1)  # 等待新代理获取

    @property
    def stop_event(self):
        return self._stop_event
